package sample.ui

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PixelFormat
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.script.GComponents
import kotlinx.coroutines.script.Block
import kotlinx.coroutines.script.XGesturePoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.script.BLACKSMITH
import kotlinx.coroutines.script.BLUE_DOOR
import kotlinx.coroutines.script.BORDER
import kotlinx.coroutines.script.BOX
import kotlinx.coroutines.script.ENEMY
import kotlinx.coroutines.script.NOT_ARRIVED
import kotlinx.coroutines.script.NPC
import kotlinx.coroutines.script.TARGET
import kotlinx.coroutines.script.PLAN
import kotlinx.coroutines.script.RED_DOOR
import kotlinx.coroutines.script.RED_DOT
import kotlinx.coroutines.script.ROAD
import kotlinx.coroutines.script.SELF
import kotlinx.coroutines.script.tes.*
import kotlinx.coroutines.withContext
import v9.assist.analyst.sMapArray
import kotlin.math.max
import kotlin.math.min

class SmallMapLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {
    companion object {
        var d1: Pair<Int, Int>? = null
        var d2: Pair<Int, Int>? = null
        var d3: Pair<Int, Int>? = null
        var d4: Pair<Int, Int>? = null
        var d5: Pair<Int, Int>? = null
        var d6: Pair<Int, Int>? = null

        var cc1: Block? = null
        var cc2: Block? = null
        var cc3: Block? = null
        var cc4: Block? = null
        var cc5: Block? = null
        var cc6: Block? = null

        private var displayPoint = false
        fun setDisplayPoint(value: Boolean) {
            // printLog { "setDisplayPoint $value" }
            displayPoint = value
        }

        private var smallMapLayout: SmallMapLayout? = null
        fun initialize(context: Context?) {
            if (context == null) return
            if (smallMapLayout != null) return
            if (!GComponents.isInitialized) {
                toast("小地图识别完成后使用")
                return
            }
            if (FloatControllerLayout.displayUserAnalysis) {
                SmallMapLayout(context).also { smallMapLayout = it } // uiThread
            }
        }

        suspend fun release() = withContext(Dispatchers.Main) {
            smallMapLayout?.removeFromWindow().also { smallMapLayout = null }
        }

        private val optionEvent = MutableLiveData<XGesturePoint?>()

    }

    private val smallMap get() = GComponents.get().smallMap
    private val windowManager by lazy { context.getSystemService(Context.WINDOW_SERVICE) as WindowManager }
    private val windowParams by lazy {
        WindowManager.LayoutParams().also {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                it.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                it.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
            }
            it.format = PixelFormat.RGBA_8888
            it.flags = (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                    or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL) // 不拦截事件
            it.gravity = Gravity.START or Gravity.TOP
            it.x = smallMap.left
            it.y = smallMap.top
            it.width = smallMap.width // 24
            it.height = smallMap.height // 24
        }
    }
    private val radius = 1.5f.dp
    private val paint by lazy { Paint().apply { color = 0x66ffffff } }
    private val points by lazy { mutableListOf<P>() }

    init {
        windowManager.addView(this, windowParams)
    }


    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        optionEvent.observe(this) {
            it?.also {
                P.createByOptionEvent(points, it)
                tryInvalidateByPoints()
            }
        }
        lifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
            while(true) {
                delay(800)
                postInvalidate()
            }
        }
    }

    private fun tryInvalidateByPoints() {
        if (points.isNotEmpty()) invalidate()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        points.toList().forEach {
            paint.alpha = max(0, min(255, (it.alpha * 255).toInt()))
            canvas.drawCircle(it.x + it.transX - smallMap.left, it.y + it.transY - smallMap.top, radius, paint)
        }
        tryInvalidateByPoints()
        //printLog { "SmallMapLayout onDraw $displayPoint" }
        if (displayPoint) {
            displayAnalysisPoint(canvas)
        }
    }

    private fun displayAnalysisPoint(canvas: Canvas) {
        //printLog { "displayAnalysisPoint" }
        if (!isDebug) return // 仅作者可见

        if ((System.currentTimeMillis() / 1000) % 2 == 0L) {

                val sMapArray: Array<IntArray>? = sMapArray
               // printLog { "draw sMapArray $sMapArray" }
                sMapArray?.let {
                    var x = 0
                   // printLog { "draw sMapArray [x:${it.size} y:${it[0].size}]" }
                    while (x < it.size) {
                        var y = 0
                        while (y < it[x].size) {
                            val type = it[x][y]
                            if (type == ROAD || type == SELF) {
                                // road 不渲染
                                paint.color =  Color.WHITE //
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            } else if (type == ENEMY) {
                                paint.color = 0xffFFD700.toInt()    // 黄
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            } else if (type == NOT_ARRIVED) {
                                paint.color = Color.GREEN    // 黄
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            } else if (type == NPC
                                || type == RED_DOT
                                || type == BLACKSMITH
                                || type == BLUE_DOOR
                                || type == BOX
                                || type == RED_DOOR) {
                                paint.color = 0xff00FFFF.toInt()
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            } else if (type == TARGET) {
                                paint.color = 0xff800080.toInt() // 紫 0xffFFD700.toInt()   //
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 4f, paint)
                            } else if (type == BORDER) {
                                paint.color = 0xffe54d26.toInt() // 红
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            } else if (type == PLAN) {
                                paint.color = 0xff7B68EE.toInt() // 蓝
                                canvas.drawCircle(x.toFloat(), y.toFloat(), 2f, paint)
                            }
                            y++
                        }
                        x++
                    }
                }


            arrayOf(d1, d2, d3, d4, d5, d6).forEach {
                it?.let {
                    paint.color = getColor("#ffff00") // 黄
                    canvas.drawCircle(it.first.toFloat(), it.second.toFloat(), radius, paint)
                }
            }

            arrayOf(cc1, cc2, cc3, cc4, cc5, cc6).forEach {
                it?.let {
                    paint.color = getColor("#33ff0000")
                    canvas.drawRect(it.rect, paint)
                }
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        points.toList().forEach { it.animator?.cancel() }
    }

    fun removeFromWindow() {
        if (isAttachedToWindow) windowManager.removeView(this)
    }

    class P {
        var x = 0
        var y = 0
        var transX = 0f
        var transY = 0f
        var alpha = 0f
        var animator: ValueAnimator? = null

        companion object {
            fun createByOptionEvent(container: MutableList<P>, o: XGesturePoint) {
                val output = P()
                when(o.type) { // 0#click ; 1#longClick ; 2#swipe
                    0, 1 -> {
                        output.x = o.points.first().first
                        output.y = o.points.first().second
                        output.animator = ValueAnimator.ofFloat(0f, 1f).apply {
                            duration = o.invokingTime
                            addUpdateListener {
                                val value = it.animatedValue as Float
                                output.alpha = if (value < 0.2f) min(1f, value * 5f) else if (value > 0.8f) max(0f, (1 - value) * 5f) else 1f
                            }
                            addListener(object : AnimatorListenerAdapter() {
                                override fun onAnimationEnd(animation: Animator) {
                                    container.remove(output)
                                }
                            })
                        }
                        container.add(output)
                        output.animator?.start()
                    }
                    2 -> {
                        output.x = o.points.first().first
                        output.y = o.points.first().second
                        output.animator = ValueAnimator.ofFloat(0f, 1f).apply {
                            duration = o.invokingTime
                            addUpdateListener {
                                val value = it.animatedValue as Float
                                output.alpha = if (value < 0.2f) min(1f, value * 5f) else if (value > 0.8f) max(0f, (1 - value) * 5f) else 1f
                                output.transX = (o.points.last().first - output.x) * value
                                output.transY = (o.points.last().second - output.y) * value
                            }
                            addListener(object : AnimatorListenerAdapter() {
                                override fun onAnimationEnd(animation: Animator) {
                                    container.remove(output)
                                }
                            })
                        }
                        container.add(output)
                        output.animator?.start()
                    }
                    else -> {
                        // do nothing
                    }
                }
            }
        }
    }
}



